/*
*
==============================================================================
*  Name        : 
*  Part of     : Omen Game Engine
*  Description : 
*  Version     : 1.0
*
*  Copyright (c) 2013 Lauri Kortevaara.
* 
==============================================================================
*/

#define OMEN_SOURCE 1

#include <OmenMath.h>

using namespace Omen;

///
/// <summary></summary>
///
Vector4d::Vector4d() :
    x(.0),y(.0),z(.0),w(.0)
{
}

///
/// <summary></summary>
///
Vector4d::Vector4d( const Omen::Float& _x, const Omen::Float& _y, const Omen::Float& _z, const Omen::Float& _w  ) :
    x(_x),y(_y),z(_z),w(_w)
{
}

float* Vector4d::operator&() 
{
    return &x; // The x, y and z members are next to each other
}

///
/// <summary></summary>
///
Vector4d::Vector4d( const Vector4d& other )
{
    memcpy( &x, &other.x, 4*sizeof(Omen::Float) );
}

///
/// <summary></summary>
///
Vector4d::~Vector4d()
{
    memset( &x, 0, 4*sizeof(Omen::Float));
}

///
/// <summary></summary>
///
Omen::Float Vector4d::length() const
{
    return sqrt( x*x+y*y+z*z+w*w );
}

///
/// <summary>Returns the squared length of this vector</summary>
///
Omen::Float Vector4d::squaredLength() const
{
    return x*x+y*y+z*z+w*w;
}

///
/// <summary></summary>
///
void Vector4d::normalize() 
{
    Omen::Float len = length();
    x /= len;
    y /= len;
    z /= len;
    w /= len;
}

///
/// <summary></summary>
///
Vector4d Vector4d::normalized() const
{
    Vector4d vec(*this);

    Omen::Float len = length();
    vec.x /= len;
    vec.y /= len;
    vec.z /= len;
    vec.z /= len;

    return vec;
}

///
/// <summary></summary>
///
void Vector4d::setCoordinates( const Omen::Float& _x, const Omen::Float& _y, const Omen::Float& _z, const Omen::Float& _w  )
{
    x = _x;
    y = _y;
    z = _z;
    w = _w;
}

///
/// <summary></summary>
///
const Omen::Float& Vector4d::operator[]( unsigned char col ) const
{
    col %= 4;
    switch( col )
    {
    case 0 : return x; break;
    case 1: return y;break;
    case 2 : return z;break;
    case 3 : return w; break;
    default: return x; break;
    }
}

///
/// <summary></summary>
///
Omen::Float& Vector4d::operator[]( unsigned char col )
{
    col %= 4;

    switch( col )
    {
    case 0 : return x; break;
    case 1:  return y;break;
    case 2 : return z;break;
    case 3: return w; break;
    default: return x; break;
    }
}

///
/// <summary></summary>
///
Vector4d& Vector4d::operator*=( Omen::Float scalar )
{
    x *= scalar;
    y *= scalar;
    z *= scalar;
    w *= scalar;

    return *this;
}

///
/// <summary></summary>
///
Vector4d& Vector4d::operator*=( const Vector4d& other )
{
    x *= other.x;
    y *= other.y;
    z *= other.z;
    w *= other.w;

    return *this;
}

///
/// <summary></summary>
///
Vector4d& Vector4d::operator+=( const Vector4d& other )
{
    x += other.x;
    y += other.y;
    z += other.z;
    w += other.w;

    return *this;
}

///
/// <summary></summary>
///
Vector4d& Vector4d::operator-=( const Vector4d& other )
{
    x -= other.x;
    y -= other.y;
    z -= other.z;
    w -= other.w;

    return *this;
}

///
/// <summary></summary>
///
Vector4d& Vector4d::operator/=( Omen::Float scalar )
{
    if( scalar != 0.0 )
    {
        x /= scalar;
        y /= scalar;
        z /= scalar;
    }
    else
    {
        *this = Vector4d();
    }
    return *this;
}

///
/// <summary></summary>
///
Vector4d Vector4d::operator*( Omen::Float scalar ) const
{
    return Vector4d( x*scalar, y*scalar, z*scalar, w*scalar );
}

///
/// <summary></summary>
///
Vector4d Vector4d::operator*( const Vector4d& other ) const
{
    return Vector4d( x*other.x, y*other.y, z*other.z, w*other.w );
}

///
/// <summary></summary>
///
Vector4d Vector4d::operator+( const Vector4d& other ) const
{
    return Vector4d( x+other.x, y+other.y, z+other.z, w+other.z );
}

///
/// <summary></summary>
///
Vector4d Vector4d::operator-( const Vector4d& other ) const
{
    return Vector4d( x-other.x, y-other.y, z-other.z, w-other.w );
}

///
/// <summary></summary>
///
Vector4d Vector4d::operator/( Omen::Float scalar ) const
{
    if( scalar != 0.0 )
    {
        return Vector4d( x/scalar, y/scalar, z/scalar, w/scalar );
    }
    else
    {
        return Vector4d();
    }
}

Vector4d& Vector4d::operator =( const Omen::Vector4d& other )
{
    x = other.x;
    y = other.y;
    z = other.z;
    w = other.w;
    return *this;
}

/// <summmry>Returns dot product of given two vectors</summary>
Omen::Float Vector4d::dotProduct ( const Vector4d& v1, const Vector4d& v2 )
{
    Vector4d v(v1);
    v *= v2;
    Omen::Float ret = static_cast<Omen::Float>(0.0);
    
    for(unsigned char i = 0; i < 3; ++i)
    {
        ret += v1[i] * v2[i];
    }
    return ret;
}
/*
///
/// <summary></summary>
///
OMEN_API Omen::Vector4d operator*( Omen::Float scalar, const Omen::Vector4d& vector )
{
    return Omen::Vector4d(vector[0]*scalar,vector[1]*scalar,vector[2]*scalar);
}

///
/// <summary></summary>
///
OMEN_API Omen::Vector4d operator* ( const Omen::Vector4d& vector, Omen::Float scalar )
{
    return Omen::Vector4d(vector[0]*scalar,vector[1]*scalar,vector[2]*scalar);
}

///
/// <summary></summary>
///
OMEN_API Omen::Vector4d operator* ( const Omen::Vector4d& v1, const Omen::Vector4d& v2 )
{
    return Omen::Vector4d(v1[0]*v2[0],v1[1]*v2[1],v1[2]*v2[2]);
}

///
/// <summary></summary>
///
OMEN_API Omen::Vector4d operator+ ( const Omen::Vector4d& v1, const Omen::Vector4d& v2 )
{
    return Omen::Vector4d(v1[0]+v2[0],v1[1]+v2[1],v1[2]+v2[2]);
}

///
/// <summary></summary>
///
OMEN_API Omen::Vector4d operator- ( const Omen::Vector4d& vector )
{
    return Omen::Vector4d(-vector[0],-vector[1],-vector[2]);
}

///
/// <summary></summary>
///
OMEN_API Omen::Vector4d  operator/ ( const Omen::Vector4d& vector, Omen::Float scalar )
{
    return Omen::Vector4d(vector[0]/scalar,vector[1]/scalar,vector[2]/scalar);
}

///
/// <summary></summary>
///
OMEN_API bool     operator== ( const Omen::Vector4d& v1, const Omen::Vector4d& v2 )
{
    return (v1[0]==v2[0] && v1[1]==v2[1] && v1[2]==v2[2]);
}

///
/// <summary></summary>
///
OMEN_API bool operator!=( const Omen::Vector4d& v1, const Omen::Vector4d& v2 )
{
    return (v1[0]!=v2[0] || v1[1]!=v2[1] || v1[2]!=v2[2]);
}
*/

/// EOF